/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "数据重组.h"


#include "节点/插座/通用插座.h"
#include "节点/socket_utils.h"
#include "节点/节点树.h"
#include "节点/输入输出节点.h"

#include <节点/插座/list/list数值插座.h>
#include <节点/插座/list/list物体插座.h>
#include <节点/插座/list/list矢量插座.h>
#include <节点/插座/list/list物理物体插座.h>

#include "异步解算/物理异步解算.h"
#include "../../node后端.h"


#include "Context/数据转换.h"

#include "变量类JIT函数.h"

#include <core/vec_conversion.h>




C_合并数据节点::C_合并数据节点(S_设备环境& ctx) : C_节点基类(DEF_合并数据节点, E_节点类型::e_节点Type_变量) {
	f_setWName(u"合并数据节点");

	C_插座基类* socket;
	DEF_创建引用插座_I(u"源");
	//DEF_创建引用插座_I(u"源2");
	f_get输入插座(1)->f_set多输入();

	DEF_通用数据插座创建_O(u"合并数据");


	m_转换后类型 = f_alloc_BoolProp(nullptr, u"类型转换");
	m_转换后类型.m_私有 = true;

}

C_合并数据节点::~C_合并数据节点() {
	f_prop_Release(m_转换后类型);
}

bool C_合并数据节点::f_update() {
	//uint32 LinkNum = f_get输入插座(1)->f_getLinkNum();

	auto* socket1 = f_get输入插座(1);
	if (socket1->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_I32);
		socket1 = f_get输入插座(1);
		auto 元素类型 = f_代码构建_数组元素取数组类型(socket1->m_Type);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, 元素类型);

		auto* outSocket1 = f_get输出插座(1);
		uint32 num = socket1->f_getLinkNum();

		S_Array* a = (S_Array*)outSocket1->f_getData(0);
		f_core_array_resize(a, 0);

		//bool 数组 = f_代码构建_是否为数组(outSocket1->m_Type);
		//if (数组) {
		//	
		//	for (uint32 i = 0; i < num; ++i) {
		//		void* data = socket1->f_getData(i);
		//
		//		f_core_array_append()
		//	}
		//	
		//	f_core_array_merge()
		//}
		//else {
		//	
		//}
		for (uint32 i = 0; i < num; ++i) {
			void* data = socket1->f_getData(i);

			if (f_代码构建_是否为指针(socket1->m_Type)) {
				f_core_array_push_back(a, (uint8*)&data);
			}
			else {
				f_core_array_push_back(a, (uint8*)data);
			}
		}
	}
	else {
		f_su_切换后端插座类型(this, e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, E_值类型::e_Type_Array);
	}
	//socket->m_Type = 源1.m_Type;
	//U_通用数据联合* data = (U_通用数据联合*)socket->f_getData(0);
	//auto& 源 = *DEF_引用插座数据(f_get输入插座(1), 0);
	return false;
}

void C_合并数据节点::f_合并物体(std::vector<S_物体*>& obs) {
	uint32 LinkNum = f_get输入插座(1)->f_getLinkNum();
	for (uint32 i = 0; i < LinkNum; ++i) {
		auto& refData = *DEF_引用插座数据(f_get输入插座(1), i);

		if (refData.m_Type == E_值类型::e_Type_Object_Array1D) {
			auto& inData = *DEF_引用转物体_1D(refData);
			obs.insert(obs.end(), inData.begin(), inData.end());
		}
		else if (refData.m_Type == E_值类型::e_Type_Object) {
			auto* inData = DEF_引用转物体(refData);
			obs.push_back(inData);
		}
	}
}

std::string	C_合并数据节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();


	
	auto* socket1 = f_get输入插座(1);

	if (socket1->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_I32);
		socket1 = f_get输入插座(1);
		auto 元素类型 = f_代码构建_数组元素取数组类型(socket1->m_Type);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, 元素类型);
		auto* outSocket1 = f_get输出插座(1);

		uint32 num = socket1->f_getLinkNum();



		std::string 变量转换代码;
		std::vector<std::string> 变量(num);
		for (uint32 i = 0; i < num; ++i) {
			变量转换代码 += socket1->f_构建变量代码(i);
			变量[i] = socket1->f_getCode(i);

			if (变量[i].empty()) {
				m_编译成功 = false;
				return "";
			}
		}

		auto 元素类型名称 = f_node_getTypeName(socket1->m_Type) + "*";

		m_Code += 变量转换代码;
		m_Code += f_node_getTypeName(outSocket1->m_Type) + "* ";
		m_Code += name + " = " + f_代码构建_创建数组(outSocket1->m_Type, num);
		for (uint32 i = 0; i < num; ++i) {
			if (f_代码构建_是否为数组(socket1->m_Type)) {
				m_Code += name + "->ptr_userData[" + f_整数值转字符串(i) + "] = (" + 元素类型名称 + ")" + DEF_S(f_core_array_from)"((S_Array*)" + 变量[i] + ");\n";
				//m_Code += DEF_S(f_core_array_copy)"((S_Array*)" + name + "->ptr_userData[" + f_整数值转字符串(i) + "], (S_Array*)" +  变量[i] + ");\n";
			}
			else {
				m_Code += name + "->ptr_userData[" + f_整数值转字符串(i) + "] = " + 变量[i] + ";\n";
			}
			//m_Code += DEF_S(f_core_array_append)"((S_Array*)" + name + ", " + 变量[i] + ");\n";
		}

		m_Code += m_ReleaseCode;
	}
	else {
		f_su_切换后端插座类型(this, e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
		f_get输出插座(1)->f_setCode("");
		return "";
	}
	f_get输出插座(1)->f_setCode(name);
	
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		
		return "";
	}
	释放 += f_代码构建_销毁数组(name);
	return m_Code;
}

void C_合并数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_转换后类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_合并数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_转换后类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建合并数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_合并数据节点(ctx);
}

C_节点基类* f_node_加载合并数据节点(S_设备环境& ctx, FILE* f) {
	C_合并数据节点* node = new C_合并数据节点(ctx);
	return node;
}

void f_node_保存合并数据节点(C_节点基类* n, FILE* f) {
	C_合并数据节点* node = dynamic_cast<C_合并数据节点*>(n);

}





C_合并数组节点::C_合并数组节点(S_设备环境& ctx) : C_节点基类(DEF_合并数组节点, E_节点类型::e_节点Type_变量) {
	f_setWName(u"合并数组");

	DEF_创建引用插座_I(u"源");
	f_get输入插座(1)->f_set多输入();

	DEF_通用数据插座创建_O(u"合并数据");
}

C_合并数组节点::~C_合并数组节点() {
	
}

bool C_合并数组节点::f_update() {
	f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_I32);

	auto* socket1 = f_get输入插座(1);
	if (socket1->f_isLink()) {
		uint32 LinkNum = socket1->f_getLinkNum();

		auto 元素类型 = f_代码构建_数组元素取数组类型(socket1->m_Type);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, 元素类型);

		auto* outSocket1 = f_get输出插座(1);
		S_Array* a = (S_Array*)outSocket1->f_getData(0);
		f_core_array_resize(a, 0);

		for (uint32 i = 0; i < LinkNum; ++i) {
			void* data = socket1->f_getData(i);
			f_core_array_insert(a, (S_Array*)data);
		}
	}
	else {
		f_su_切换后端插座类型(this, e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, E_值类型::e_Type_Array);
	}

	return false;
}

void C_合并数组节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_转换后类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_合并数组节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_转换后类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建合并数组节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_合并数组节点(ctx);
}

C_节点基类* f_node_加载合并数组节点(S_设备环境& ctx, FILE* f) {
	C_合并数组节点* node = new C_合并数组节点(ctx);
	return node;
}

void f_node_保存合并数组节点(C_节点基类* n, FILE* f) {
	C_合并数组节点* node = dynamic_cast<C_合并数组节点*>(n);

}







C_转换数据节点::C_转换数据节点(S_设备环境& ctx) : C_节点基类("转换数据节点") {
	f_setWName(u"转换数据");

	C_插座基类* socket;
	DEF_创建引用插座_I(u"源1");
	DEF_创建引用插座_O(u"新数据");

	m_转换数据类型 = E_值类型::e_Type_None;

	m_转换后类型 = f_alloc_EnumProp(nullptr,
		{ {u"相交点转线段", u""}, {u"vec[]", u""}, {u"线段", u""}, {u"Mesh", u""}, {u"碰撞三角形中点", u""} },
		u"转换数据",
		0,
		nullptr
	);
}

C_转换数据节点::~C_转换数据节点() {
}

bool C_转换数据节点::f_update() {
	auto& 输入数据 = *DEF_引用插座数据(f_get输入插座(1), 0);
	
	
	uint8 转换后类型 = f_prop_enum(m_转换后类型);
	switch (输入数据.m_Type) {
	case E_值类型::e_插座Type_Line_Array1D: {
		auto& lines = *((std::vector<S_线段>*)(输入数据.m_Data));
		uint32 num = lines.size();
		auto* p_line = lines.data();


		switch (转换后类型) {
		case 0: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_插座Type_Line_Array1D);

			auto& outData = *DEF_线段_1D插座数据(f_get输出插座(1));
			outData.resize(num);
			auto p_outData = outData.data();
			for (uint32 i = 0; i < num; ++i) {
				p_outData[i].begin = p_line[i].begin;
				p_outData[i].end = p_line[i].begin + p_line[i].end;
			}

		}

		case 1: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_Array1D);

			auto& outData = *DEF_Vec3_Array1D插座数据(f_get输出插座(1));
			outData.resize(num);
			auto p_outData = outData.data();

			for (uint32 i = 0; i < num; ++i) {
				p_outData[i] = p_line[i].begin;
			}
		}
		}
		break;
	}

	case E_值类型::e_Type_Vec3_Array1D: {
		std::vector<vec3>& v3 = *((std::vector<vec3>*)(输入数据.m_Data));

		switch (转换后类型) {
		case 2: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_插座Type_Line_Array1D);
			auto& 线段 = *DEF_线段_1D插座数据(f_get输出插座(1));

			uint32 num = v3.size() / 2;
			线段.resize(num);
			for (uint32 i = 0; i < num; ++i) {
				线段[i].begin = v3[i * 2];
				线段[i].end = v3[i * 2 + 1];
			}
			break;
		}
		
		case 3: {
			
			break;
		}
		}
		break;
	}

	case E_值类型::e_插座Type_八叉树: {
		auto& tree = *DEF_引用转八叉树(输入数据);
		//f_get八叉树成员(转换后类型, tree);
		break;
	}
	
	case E_值类型::e_Type_Object: {
		auto* ob = DEF_引用转物体(输入数据);
		f_物体数据转换(转换后类型, { ob });
		break;
	}
	case E_值类型::e_Type_Object_Array1D: {
		auto& obs = *DEF_引用转物体_1D(输入数据);
		f_物体数据转换(转换后类型, obs);
	}
	case E_值类型::e_Type_VN_Array1D: {
		auto& VN = *DEF_引用转VN_1D(输入数据);
		f_VN数据转换(转换后类型, VN);
	}
	}
	return false;


	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, m_转换数据类型);
	switch (m_转换数据类型) {
	case E_值类型::e_Type_VecSphere_1D: {
		if (输入数据.m_Type == E_值类型::e_插座Type_物理解算器) {
		} else if (输入数据.m_Type == E_值类型::e_Type_Vec4_Array1D) {
		}
		else if (输入数据.m_Type == E_值类型::e_Type_Mesh) {
		}
		break;
	}
	case E_值类型::e_Type_Vec3_Array1D: {

		break;
	}
	case E_值类型::e_Type_Vec4_Array1D: {
		if (输入数据.m_Type == E_值类型::e_插座Type_树路径) {
			auto& tree = *((std::vector<S_八叉树子空间*>*)输入数据.m_Data);
			uint32 num = tree.size();
			auto* data = tree.data();

			std::vector<vec4> vert(num);
			auto* vert_p = vert.data();
			for (uint32 i = 0; i < num; ++i) {
				vert_p[i] = { data[i]->m_坐标.x, data[i]->m_坐标.y, data[i]->m_坐标.z, data[i]->m_域大小 };
			}
			f_get输出插座(1)->f_setData(&vert);
		}
		else if (输入数据.m_Type == E_值类型::e_Type_Vec4_Array1D) {

		}
		break;
	}
	case E_值类型::e_插座Type_树路径: {
		break;
	}
	case E_值类型::e_Type_Mesh_线1D: {
		break;
	}
	case E_值类型::e_插座Type_Line_Array1D: {
		break;
	}
	case E_值类型::e_Type_Mesh_面中心1D: {
		if (输入数据.m_Type == E_值类型::e_Type_Mesh) {
			auto& outData = *DEF_Vec3_Array1D插座数据(f_get输出插座(1));
			outData.clear();
			f_网格数据_取面中心坐标(outData, (S_Mesh*)输入数据.m_Data);
		}
		break;
	}
	}
	return false;
}

void C_转换数据节点::f_物体数据转换(uint8 转换后类型, const std::vector<S_物体*>& objs) {
	switch (转换后类型) {
	case 0:
		break;
	case 3: {
		if (objs.size() == 1) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mesh);
			auto& 网格 = *DEF_网格插座数据(f_get输出插座(1));

		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mesh_1D);
			auto 网格 = DEF_网格插座_1D数据(f_get输出插座(1), 0);

			uint32 num = objs.size();
			f_core_array_resize((S_Array*)网格, num);
			for (uint32 i = 0; i < num; ++i) {
				auto* mesh = f_ob_getMesh(objs[i]);
				if (网格->ptr_userData[i] == nullptr) 网格->ptr_userData[i] = f_surface_创建网格对象(E_网格数据枚举::e_Mesh_CPU);
				f_surface_Copy(网格->ptr_userData[i], mesh);
			}
		}

		break;
	}
	}
}

void C_转换数据节点::f_VN数据转换(uint8 转换后类型, const std::vector<S_VN>& vns) {
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_插座Type_Line_Array1D);
	auto& outData = *DEF_线段_1D插座数据(f_get输出插座(1));

	uint32 num = vns.size();
	outData.resize(num);
	auto* p_line = vns.data();
	auto* p_outData = outData.data();

	for (uint32 i = 0; i < num; ++i) {
		p_outData[i].begin = p_line[i].vert;
		p_outData[i].end = vec_add(p_line[i].vert, p_line[i].normal);
	}

	switch (转换后类型) {
	case 2: {
		
	}
	}
}

/*S_插座增减方式	C_转换数据节点::f_动态增减插座(E_插座输出方向 方向) {
	E_数据赋值方式 插座操作方式;

	uint16 num = f_get输入插座Num();
	if (num >= 3 && f_get输入插座(num - 2)->f_isLink() == false) {
		return { nullptr, E_数据赋值方式::e_赋值_None };
	}


	C_插座基类* socket;
	if (方向 == E_插座输出方向::e_插座Type_输入) {
		DEF_创建引用插座_I("源1");
	}

	f_set是否要更新(true);
	return { socket, 插座操作方式 };

}*/

C_节点基类* f_node_加载转换数据节点(S_设备环境& ctx, FILE* f) {
	C_转换数据节点* node = new C_转换数据节点(ctx);
	fread(&(((S_PropValueEnum*)node->m_转换后类型.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	return node;
}

void f_node_保存转换数据节点(C_节点基类* n, FILE* f) {
	C_转换数据节点* node = dynamic_cast<C_转换数据节点*>(n);
	fwrite(&(((S_PropValueEnum*)node->m_转换后类型.m_Value)->m_当前选项), sizeof(uint8), 1, f);
}














static void on_切换取成员数据(S_Props& prop) {
	switch (f_prop_enum(prop)) {
	case 0: {

		break;
	}
	default:
		break;
	}
}

C_取成员数据节点::C_取成员数据节点(S_设备环境& ctx) : C_节点基类("取成员数据节点") {
	f_setWName(u"取成员数据");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建引用插座_I(u"源1");
	DEF_创建UI32插座_I(u"下标");

	DEF_创建引用插座_O(u"成员");
	
	m_成员 = f_alloc_EnumProp(nullptr,
		{ {u"碰撞空间树", u""}, {u"碰撞三角形中点", u""}, {u"域顶点", u""} },
		u"物理引擎成员", 
		0, 
		on_切换取成员数据
	);
	m_不同输入数据成员类型.push_back(m_成员);

	m_成员 = f_alloc_EnumProp(nullptr,
		{ {u"点", u""}, {u"面球形包围", u""}, {u"面法线", u""}, {u"点法线", u""}, {u"线段", u""}, {u"树单元", u""}, {u"网格", u""}, {u"索引", u""} },
		u"网格成员", 
		0, 
		on_切换取成员数据
	);
	m_不同输入数据成员类型.push_back(m_成员);


}

C_取成员数据节点::~C_取成员数据节点() {
}

void C_取成员数据节点::f_插座连接事件(C_插座基类* 发生链接的输入插座) {
	auto& 输入数据 = *DEF_引用插座数据(f_get输入插座(1), 0);

	switch (输入数据.m_Type) {
	case E_值类型::e_插座Type_物理解算器: {
		m_成员 = m_不同输入数据成员类型[0];
		break;
	}
	case E_值类型::e_插座Type_八叉树:
	case E_值类型::e_Type_Object:
	case E_值类型::e_Type_Vec3_Array1D:
	case E_值类型::e_Type_Object_Array1D:
	case E_值类型::e_Type_Mesh: {
		m_成员 = m_不同输入数据成员类型[1];
		break;
	}
	}

	f_set是否要更新(true);
}

void C_取成员数据节点::f_get物理引擎成员(uint8 成员, S_Physics* 解算器) {
	switch (成员) {
	case 0: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec4_Array1D);

		auto& 单元坐标 = *DEF_Vec4插座_1D数据(f_get输出插座(1));
		//单元坐标.clear();
		//f_Phy_get静态碰撞空间树调试数据(解算器, 单元坐标);
		break;
	}

	case 1: {

		break;
	}

	case 2: {
		auto 下标 = DEF_UI32插座数据(f_get输入插座(2));

		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_Array1D);
		auto& 粒子坐标 = *DEF_Vec3_Array1D插座数据(f_get输出插座(1));
		粒子坐标.clear();

		if (解算器->m_IdType == E_物理引擎::E_物理引擎_PBF) {
			//f_Phy_get域中粒子(解算器, )
		}

		break;
	}

	}
}

void C_取成员数据节点::f_get网格成员(uint8 成员, const std::vector<S_Mesh*>& meshs) {
	uint32 num = meshs.size();

	switch (成员) {
	case 0: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_Array1D);
		auto& 中心点 = *DEF_Vec3_Array1D插座数据(f_get输出插座(1));

		中心点.clear();
		for (uint32 i = 0; i < num; ++i) {
			f_surface_计算面中心点(meshs[i], 中心点);
		}
		break;
	}
	case 1: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_VecSphere_1D);
		auto& 包围盒 = *DEF_VecSphere_1D插座数据(f_get输出插座(1));
		
		包围盒.clear();
		for (uint32 i = 0; i < num; ++i) {
			f_surface_计算三角形球体包围盒(meshs[i], 包围盒);
		}
		
		break;
	}

	case 6: {
		if (meshs.size() == 1) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mesh);
			auto& mesh = *DEF_网格插座数据(f_get输出插座(1));
			
		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mesh_1D);
			auto& 新网格 = *DEF_网格插座_1D数据(f_get输出插座(1), 0);
		}
		
		break;
	}
	}
}

void C_取成员数据节点::f_get向量成员(uint8 成员, const std::vector<vec3>& v3) {
	uint32 num = v3.size();

	switch (成员) {
	case 4: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_插座Type_Line_Array1D);
		auto& 线段 = *DEF_线段_1D插座数据(f_get输出插座(1));
		num /= 2;
		线段.resize(num);
		for (uint32 i = 0; i < num; ++i) {
			线段[i].begin = v3[i * 2];
			线段[i].end = v3[i * 2 + 1];
		}
		break;
	}
	}
}

void C_取成员数据节点::f_get八叉树成员(uint8 成员, const S_点距八叉树& tree) {
	//auto& inData2 = *DEF_转换为引用数据(f_get输入插座(2), 0);

	switch (成员) {
	case 0: {
		if (tree.m_映射的数据类型 == E_值类型::e_Type_Mesh) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_Array1D);
			auto& outData = *DEF_Vec3_Array1D插座数据(f_get输出插座(1));

			outData.clear();
			f_surface_计算面中心点((S_Mesh*)tree.m_映射的数据, outData);
		}
		break;
	}

	case 1: {
		if (tree.m_映射的数据类型 == E_值类型::e_Type_Mesh) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_VecSphere_1D);
			auto& outData = *DEF_VecSphere_1D插座数据(f_get输出插座(1));

			outData.clear();
			f_surface_计算三角形球体包围盒((S_Mesh*)tree.m_映射的数据, outData);
		}
		break;
	}

	case 3: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mesh);
		auto& Mesh = *DEF_网格插座数据(f_get输出插座(1), 0);

		if (tree.m_映射的数据类型 == E_值类型::e_Type_Mesh) {

		}
		break;
	}

	case 4: {
		if (tree.m_映射的数据类型 == E_值类型::e_Type_Mesh) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_VecSphere_1D);
			auto& outData = *DEF_VecSphere_1D插座数据(f_get输出插座(1));

			outData.clear();
			f_surface_计算三角形球体包围盒((S_Mesh*)tree.m_映射的数据, outData);
		}
		break;
	}

	case 6: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mesh);
		auto& Mesh = *DEF_网格插座数据(f_get输出插座(1), 0);
		
		break;
	}

	case 7: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32_1D);
		auto& 三角形索引 = *DEF_UI32插座_1D数据(f_get输出插座(1), 0);

		if (tree.m_映射的数据类型 == E_值类型::e_Type_Mesh) {
			//auto 顶点 = (vec3*)(((S_Mesh*)(tree.m_映射的数据))->f_map顶点()).point;
			//auto 索引 = (uvec3*)(((S_Mesh*)(tree.m_映射的数据))->f_map索引()).point;

		}
		break;
	}
	}
	
}

void C_取成员数据节点::f_get路径树成员(uint8 成员, const std::vector<S_八叉树子空间*>& treePath) {
	switch (成员) {
	case 0: {
		auto& inData2 = *DEF_引用插座数据(f_get输入插座(2), 0);

		switch (inData2.m_Type) {
		case E_值类型::e_Type_Object_Array1D: {

		}
		}

		for (auto& e : treePath) {
			auto& indexs = *((std::vector<uint32>*)(e->m_数据));

		}
	}

	case 7: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32_1D);
		auto& 三角形索引 = *DEF_UI32插座_1D数据(f_get输出插座(1), 0);

		for (auto& e : treePath) {
			auto& indexs = *((std::vector<uint32>*)(e->m_数据));

			//三角形索引.reserve(三角形索引.size() + indexs.size());
			//for (auto i : indexs) {
			//	三角形索引.push_back(i);
			//}
		}
		break;
	}
	}
}

bool C_取成员数据节点::f_update() {
	auto& 输入数据 = *DEF_引用插座数据(f_get输入插座(1), 0);

	//f_切换插座类型(this, E_插座输出方向::e_插座Type_输出, 1, m_转换数据类型);
	uint8 成员项 = f_prop_enum(m_成员);
	switch (输入数据.m_Type) {
	case E_值类型::e_插座Type_物理解算器: {
		auto& 输入数据 = *DEF_引用插座数据(f_get输入插座(1), 0);
		f_get物理引擎成员(成员项, (S_Physics*)(输入数据.m_Data));
		break;
	}
	case E_值类型::e_Type_Mesh: {
		f_get网格成员(成员项, { (DEF_引用转MESH(输入数据)) });
		break;
	}
	
	case E_值类型::e_Type_Object: {
		auto ob = DEF_引用转物体(输入数据);
		S_Mesh* mesh = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_面);

		f_get网格成员(成员项, { mesh });
		break;
	}

	case E_值类型::e_Type_Object_Array1D: {
		std::vector<S_物体*>& objs = *((std::vector<S_物体*>*)(输入数据.m_Data));
		std::vector<S_Mesh*> meshs; 
		meshs.reserve(objs.size());
		for (auto& ob : objs) {
			S_Mesh* mesh = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_面);
			meshs.push_back(mesh);
		}
		if(meshs.size()) f_get网格成员(成员项, meshs);
		break;
	}
	case E_值类型::e_Type_Vec3_Array1D: {
		std::vector<vec3>& v3 = *((std::vector<vec3>*)(输入数据.m_Data));
		f_get向量成员(成员项, v3);
		break;
	}
	case E_值类型::e_插座Type_Line: {
		break;
	}
	case E_值类型::e_插座Type_八叉树: {
		auto& tree = *DEF_引用转八叉树(输入数据);
		f_get八叉树成员(成员项, tree);
		break;
	}
	case E_值类型::e_插座Type_树路径: {
		auto& treePath = *DEF_引用转路径树(输入数据);
		f_get路径树成员(成员项, treePath);
		break;
	}
	case E_值类型::e_Type_体素: {
		auto& 体素 = *DEF_引用转体素(输入数据);
		f_get体素成员(成员项, 体素);
		break;
	}
	}
	return false;
}

void C_取成员数据节点::f_get体素成员(uint8 成员, S_体素& 体素) {
	switch (成员) {
	case 0: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_Array1D);
		auto& 体素坐标 = *DEF_Vec3_Array1D插座数据(f_get输出插座(1), 0);

		体素坐标 = 体素.m_坐标;
	}

	case 7: {
		
		break;
	}
	}
}


C_节点基类* f_node_加载取成员数据节点(S_设备环境& ctx, FILE* f) {
	C_取成员数据节点* node = new C_取成员数据节点(ctx);

	fread(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);

	return node;
}

void f_node_保存取成员数据节点(C_节点基类* n, FILE* f) {
	C_取成员数据节点* node = dynamic_cast<C_取成员数据节点*>(n);

	fwrite(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);

}






C_从坐标取数据节点::C_从坐标取数据节点(S_设备环境& ctx) : C_节点基类(DEF_从坐标取数据节点) {
	f_setWName(u"从坐标取数据节点");
	m_Ctx = ctx;
	m_是否多线程 = true;

	C_插座基类* socket;
	DEF_创建数组插座_I(u"数组");
	DEF_创建iVec3插座_I(u"维度");
	DEF_创建iVec3插座_I(u"坐标");

	DEF_创建引用插座_O(u"成员");

	m_成员 = f_alloc_EnumProp(nullptr,
		{ {u"坐标域粒子", u""}, {u"碰撞三角形中点", u""}, {u"域顶点", u""} },
		u"物理引擎成员",
		0,
		on_切换取成员数据
	);
	
}

C_从坐标取数据节点::~C_从坐标取数据节点() {
	f_prop_Release(m_成员);
}

void C_从坐标取数据节点::f_异步解算() {
	auto& 输入数据 = *DEF_引用插座数据(f_get输入插座(1), 0);
}

bool C_从坐标取数据节点::f_update() {
	
	return false;
}

std::string	C_从坐标取数据节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto* rt = f_getThis节点树();
	std::string name = f_getName();

	f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	auto* sokcet1 = f_get输入插座(1);
	auto* sokcet2 = f_get输入插座(2);
	auto* sokcet3 = f_get输入插座(3);

	auto 类型名称 = f_数组元素插座切换(this, E_插座方向::e_插座Type_输出, 1, sokcet1->m_Type);
	
	if (f_代码构建_数组指针(sokcet1)) {
		
	}
	
	bool 创建数组 = false;

	m_Code += "{\n";
	m_Code += sokcet1->f_构建变量代码(0);
	

	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_从坐标取数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_成员, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_从坐标取数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_成员, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建从坐标取数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_从坐标取数据节点(ctx);
}

C_节点基类* f_node_加载从坐标取数据节点(S_设备环境& ctx, FILE* f) {
	C_从坐标取数据节点* node = new C_从坐标取数据节点(ctx);
	return node;
}

void f_node_保存从坐标取数据节点(C_节点基类* n, FILE* f) {
	C_从坐标取数据节点* node = dynamic_cast<C_从坐标取数据节点*>(n);
}






C_单值钳制节点::C_单值钳制节点(S_设备环境& ctx) : C_节点基类(DEF_单值钳制节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"钳制");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建F32插座_I(u"变量", nullptr);
	DEF_创建F32插座_O(u"值", nullptr);

	m_区间 = f_alloc_Vec2Prop(nullptr, u"轴向");
	m_区间.m_私有 = true;

	f_prop_Vec2(m_区间) = { 0,1 };

	f_构建代码_分配渲染器GPU属性变量(m_区间);
	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
}

C_单值钳制节点::~C_单值钳制节点() {
	f_构建代码_释放渲染器GPU属性变量(m_区间);
	f_构建代码_释放GPU插座变量(*f_get输入插座(1));
}

bool C_单值钳制节点::f_update() {
	return false;
}

std::string	C_单值钳制节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";
	auto* rt = f_getThis节点树();

	f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
	auto* sokcet1 = f_get输入插座(1);

	std::string 新变量 = f_getName();
	bool 创建数组 = false;
	if (sokcet1->m_Type == E_值类型::e_Type_F32_1D) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);
		创建数组 = true;

		m_Code += "S_F32Array* " + 新变量 + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
		m_Code += "float " + 新变量 + ";\n";
	}
	
	std::string 钳制区间变量 = f_代码构建_属性变量(m_区间, rt);
	
	m_Code += "{\n";
	m_Code += sokcet1->f_构建变量代码(0);

	switch (rt->m_树类型) {
		case E_节点树类型::e_type_几何着色节点树:
		case E_节点树类型::e_type_并行节点树:
		case E_节点树类型::e_type_着色节点树: {
			m_Code += 新变量 + " = " + DEF_S(clamp)"(";
			m_Code += sokcet1->f_getCode(0) + ", " + 钳制区间变量 + ".x, " + 钳制区间变量 + ".y);\n";
			f_代码构建_属性变量传至GPU(m_区间);
			break;
		}
		default:
			if (创建数组) {
				std::string 数量 = f_代码构建_Array数组数量(sokcet1->f_getCode(0));
				m_Code += 新变量 + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, 数量);
				m_Code += DEF_S(f_JIT_Fun_Clamp)"(";
				m_Code += 新变量 + "->ptr_userData, " + sokcet1->f_getCode(0) + "->ptr_userData, " + 数量 + ", " + 钳制区间变量 + ");\n";
			}
			else {
				m_Code += 新变量 + " = " + "DEF_Min(DEF_Max( (" + 钳制区间变量 + ").x, " + sokcet1->f_getCode(0) + "), (" + 钳制区间变量 + ").y);\n";
			}
			break;
	}
	

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(新变量);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(新变量));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(新变量);
	}
	return m_Code;
}

void C_单值钳制节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_区间, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_单值钳制节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_区间, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建单值钳制节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单值钳制节点(ctx);
}

C_节点基类* f_node_加载单值钳制节点(S_设备环境& ctx, FILE* f) {
	C_单值钳制节点* node = new C_单值钳制节点(ctx);
	return node;
}

void f_node_保存单值钳制节点(C_节点基类* n, FILE* f) {
	C_单值钳制节点* node = dynamic_cast<C_单值钳制节点*>(n);
}




C_矢量钳制节点::C_矢量钳制节点(S_设备环境& ctx) : C_节点基类(DEF_矢量钳制节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"钳制");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(u"变量", nullptr);
	DEF_创建Vec3插座_I(u"最小", nullptr);
	DEF_创建Vec3插座_I(u"最大", nullptr);

	DEF_创建Vec3插座_O(u"值", nullptr);


	m_改变原数据 = f_alloc_BoolProp(nullptr, u"改变原数据");
	m_改变原数据.m_私有 = true;
	f_prop_Bool(m_改变原数据) = false;

}

C_矢量钳制节点::~C_矢量钳制节点() {
	f_prop_Release(m_改变原数据);
}

bool C_矢量钳制节点::f_update() {
	return false;
}

std::string	C_矢量钳制节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();

	auto* rt = f_getThis节点树();

	//f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	auto* sokcet1 = f_get输入插座(1);
	
	bool 创建数组 = false;



	switch (sokcet1->f_get接入的数据类型()) {
		case E_值类型::e_Type_Vec3_1D:
			创建数组 = true;
			break;
		case E_值类型::e_Type_Vec3:
			break;
		default:
			return "";
	}

	if (sokcet1->f_isLink() == false) {
		创建数组 = false;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Vec3_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_1D);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Vec3);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3);
	}

	auto* sokcet2 = f_get输入插座(2);
	auto* sokcet3 = f_get输入插座(3);


	if (创建数组) {
		m_Code += DEF_S(S_Vec3Array*)" " + name + ";\n";
	}
	else {
		m_Code += "vec3 " + name + ";\n";
	}
	

	m_Code += "{\n";
	m_Code += sokcet1->f_构建变量代码(0);
	m_Code += sokcet2->f_构建变量代码(0);
	m_Code += sokcet3->f_构建变量代码(0);

	if (创建数组) {
		std::string 数量 = f_代码构建_Array数组数量(sokcet1->f_getCode(0));
		m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, 数量);
		m_Code += DEF_S(f_JIT_Fun_Vec3Clamp)"(" + sokcet1->f_getCode(0) + ", " + sokcet2->f_getCode(0) + ", " + sokcet3->f_getCode(0) + ", " + name + ");\n";
	}
	else {
		m_Code += name + " = " + DEF_S(clamp)"("+ sokcet1->f_getCode(0) + ", " + sokcet2->f_getCode(0) + ", " + sokcet3->f_getCode(0) + ");\n";
	}

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_矢量钳制节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_改变原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_矢量钳制节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_改变原数据, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建矢量钳制节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_矢量钳制节点(ctx);
}

C_节点基类* f_node_加载矢量钳制节点(S_设备环境& ctx, FILE* f) {
	C_矢量钳制节点* node = new C_矢量钳制节点(ctx);
	return node;
}

void f_node_保存矢量钳制节点(C_节点基类* n, FILE* f) {
	C_矢量钳制节点* node = dynamic_cast<C_矢量钳制节点*>(n);
}




C_取内存邻接数据节点::C_取内存邻接数据节点(S_设备环境& ctx) : C_节点基类(DEF_取内存邻接数据节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"取内存邻接数据");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建数组插座_I(u"数组");
	DEF_创建UI32插座_I(u"偏移");

	DEF_创建UI32插座_O(u"前");
	DEF_创建UI32插座_O(u"中");
	DEF_创建UI32插座_O(u"后");
}

C_取内存邻接数据节点::~C_取内存邻接数据节点() {
}

bool C_取内存邻接数据节点::f_update() {
	return false;
}
std::string	C_取内存邻接数据节点::DEF_节点编译函数 {
	m_Code = "";
    m_ReleaseCode = "";
	auto name = f_getName();

	f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	switch (socket1->f_get接入的数据类型()) {
	case E_值类型::e_Type_F32_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_F32); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_F32); 
		break;
	case E_值类型::e_Type_I32_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_I32); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_I32); 
		break;
	case E_值类型::e_Type_UI32_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_UI32); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_UI32); 
		break;
	case E_值类型::e_Type_Vec2_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec2);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_Vec2);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_Vec2);
		break;
	case E_值类型::e_Type_Vec3_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_Vec3); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_Vec3); 
		break;
	case E_值类型::e_Type_Vec4_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec4); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_Vec4); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_Vec4); 
		break;
	case E_值类型::e_Type_uVec2_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_uVec2); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_uVec2); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_uVec2); 
		break;
	case E_值类型::e_Type_uVec3_1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_uVec3); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_uVec3); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_uVec3); 
		break;
	case E_值类型::e_Type_多边形边1D: 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_多边形边); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_多边形边); 
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_多边形边); 
		break;
	}

	socket1 = f_get输入插座(1);
	auto* outSocket1 = f_get输出插座(1);
	auto* outSocket2 = f_get输出插座(2);
	auto* outSocket3 = f_get输出插座(3);
	if (socket1->f_isLink()) {
		m_Code += socket1->f_构建变量代码(0);
		m_Code += socket2->f_构建变量代码(0);


		std::string 元素0 = name + "元素ID0";
		std::string 元素1 = name + "元素ID1";
		std::string 元素2 = name + "元素ID2";
		std::string 数组 = socket1->f_getCode(0);
		std::string offset = name + "_offset";

		m_Code += DEF_S(uint32)" " + offset + " = " + socket2->f_getCode(0) + ";\n";

		m_Code += "if(" + offset + " >= " + 数组 + "->count){\n";
		m_Code += offset + " = " + 数组 + "->count - 1;\n";
		m_Code += "}\n";

		if (outSocket1->f_isLink()) {
			m_Code += "uint32 " + 元素0 + " = " + offset + ";\n";
			m_Code += "if(" + offset + " > 0){\n";
			m_Code += 元素0 + " -= 1;\n";
			m_Code += "}\n";

			outSocket1->f_setCode(f_生成元素引用代码(socket1->m_Type, name+"_前", 数组, 元素0));
		}
		if (outSocket2->f_isLink()) {
			m_Code += "uint32 " + 元素1 + " = " + offset + ";\n";

			outSocket2->f_setCode(f_生成元素引用代码(socket1->m_Type, name+"_中", 数组, 元素1));
		}
		if (outSocket3->f_isLink()) {
			m_Code += "uint32 " + 元素2 + " = " + offset + ";\n";
			m_Code += "if(" + 元素2 + " < " + "((" + 数组 + ")->count - 2)){\n";
			m_Code += 元素2 + " += 1;\n";
			m_Code += "} else {\n";
			m_Code += 元素2 + " = ((" + 数组 + ")->count - 1);\n";
			m_Code += "}\n";

			outSocket3->f_setCode(f_生成元素引用代码(socket1->m_Type, name+"_后", 数组, 元素2));
		}
	}
	else {
		outSocket1->f_setCode("");
		outSocket2->f_setCode("");
		outSocket3->f_setCode("");
	}
	
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		
		return "";
	}
	return m_Code;
}

std::string C_取内存邻接数据节点::f_生成元素引用代码(E_值类型 type, const std::string& name, std::string& 数组, std::string& 元素ID) {
	switch (type) {
	case E_值类型::e_Type_F32_1D:
		m_Code += "float32 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_F32Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : 0;\n";
		break;
	case E_值类型::e_Type_I32_1D:
		m_Code += "int32 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_I32Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : 0;\n";
		break;
	case E_值类型::e_Type_UI32_1D:
		m_Code += "uint32 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_UI32Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : 0;\n";
		break;
	case E_值类型::e_Type_Vec2_1D:
		m_Code += "vec2 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_Vec2Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : vec2{};\n";
		break;
	case E_值类型::e_Type_Vec3_1D:
		m_Code += "vec3 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_Vec3Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : vec3{};\n";
		break;
	case E_值类型::e_Type_Vec4_1D:
		m_Code += "vec3 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_Vec4Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : vec4{};\n";
		break;
	case E_值类型::e_Type_iVec2_1D:
		m_Code += "ivec2 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_iVec2Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : ivec2{};\n";
		break;
	case E_值类型::e_Type_iVec3_1D:
		m_Code += "ivec3 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_iVec3Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : ivec3{};\n";
		break;
	case E_值类型::e_Type_uVec2_1D:
		m_Code += "uvec2 " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_uVec2Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : uvec2{};\n";
		break;
	case E_值类型::e_Type_多边形边1D:
		m_Code += "S_边* " + name + " = " + 数组 + "->count ? (((" + DEF_S(S_边Array) + "*)(" + 数组 + "))->ptr_userData[" + 元素ID + "]) : nullptr;\n";
		break;
	}
	return name;
}

C_节点基类* f_node_创建取内存邻接数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_取内存邻接数据节点(ctx);
}

C_节点基类* f_node_加载取内存邻接数据节点(S_设备环境& ctx, FILE* f) {
	C_取内存邻接数据节点* node = new C_取内存邻接数据节点(ctx);
	return node;
}

void f_node_保存取内存邻接数据节点(C_节点基类* n, FILE* f) {
	C_取内存邻接数据节点* node = dynamic_cast<C_取内存邻接数据节点*>(n);
}



C_取空间邻接数据节点::C_取空间邻接数据节点(S_设备环境& ctx) : C_节点基类(DEF_取空间邻接数据节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"取空间邻接数据");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建iVec3_1D插座_I(u"数组");
	DEF_创建iVec3插座_I(u"坐标");
	DEF_创建iVec3插座_I(u"分辨率");

	DEF_创建iVec3_1D插座_O(u"邻接");
	DEF_创建I8_1D插座_O(u"标记");

	m_空间类型 = f_alloc_EnumProp(nullptr, {
		{u"3X3",		u""},
		{u"十字轴向",	u""},
		{u"坐标",		u""},
	}, u"空间类型");
	m_空间类型.m_私有 = true;
	f_prop_enum(m_空间类型) = 1;

	m_填充 = f_alloc_F32Prop(nullptr, u"填充");
	m_空间类型.m_私有 = true;
	f_prop_F32(m_填充) = 0;

}

C_取空间邻接数据节点::~C_取空间邻接数据节点() {
	f_prop_Release(m_空间类型);
}

bool C_取空间邻接数据节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(3);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_iVec3_1D);
		socket1 = f_get输入插座(1);

		f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		socket2 = f_get输入插座(2);
		outSocket1 = f_get输出插座(3);

		f_JIT_坐标轴邻接数据((S_Array*)DEF_iVec3插座_1D数据(socket1), DEF_iVec3插座数据(socket2), DEF_iVec3插座数据(socket3), (S_Array*)DEF_iVec3插座_1D数据(outSocket1));
	}

	return false;
}

std::string	C_取空间邻接数据节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";
	auto name_A = f_getName() + "_OutA";
	auto name_B = f_getName() + "_OutB";
	bool 创建数组 = false;

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(1);
	auto* outSocket2 = f_get输出插座(2);


	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_iVec3_1D);
		socket1 = f_get输入插座(1);

		


		std::string 类型名称;
		switch (f_prop_enum(m_空间类型)) {
			case 0: {
				//类型名称 = f_node_getDataTypeName(接入的数据类型);
				//创建数组 = true;
				//
				//m_Code += 类型名称 + "* " + name_A + " = " + f_代码构建_创建Array(接入的数据类型, "0");
				//m_Code += DEF_S(S_I8Array*)" " + name_B + " = " + f_代码构建_创建Array(E_值类型::e_Type_I8_1D, "27");
				//break;
			}
			case 1: {
				f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
				f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
				类型名称 = f_node_getTypeName(接入的数据类型);
				创建数组 = true;

				m_Code += 类型名称 + "* " + name_A + " = " + f_代码构建_创建Array(接入的数据类型, "0");
				m_Code += DEF_S(S_I8Array*)" " + name_B + " = " + f_代码构建_创建Array(E_值类型::e_Type_I8_1D, "27");
				break;
			}

			case 2: {
				auto 输出类型 = f_代码构建_数组元素类型(socket1->m_Type);
				f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
				f_su_切换后端插座类型(this, e_插座Type_输出, 1, 输出类型);

				类型名称 = f_node_getTypeName(输出类型);
				break;
			}
		}

		
		

		
		socket2 = f_get输入插座(2);
		outSocket1 = f_get输出插座(1);
		outSocket2 = f_get输出插座(2);


		//m_Code += "{\n";
		m_Code += socket1->f_构建变量代码(0);
		m_Code += socket2->f_构建变量代码(0);
		m_Code += socket3->f_构建变量代码(0);

		switch (f_prop_enum(m_空间类型)) {
			case 0: {
				m_Code += DEF_S(f_JIT_3X3邻接数据)"((S_Array*)" + socket1->f_getCode(0);
				m_Code += ", " + socket2->f_getCode(0);
				m_Code += ", " + socket3->f_getCode(0);
				m_Code += ", (S_Array*)" + name_A;
				m_Code += ", " + name_B + ");\n";

				break;
			}
			case 1: {
				//m_Code += name + " = (" + 类型名称 + "*)";
				m_Code += DEF_S(f_JIT_坐标轴邻接数据)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ", (S_Array*)" + name_A + ");\n";
				break;
			}
			case 2: {
				m_Code += "auto& " + name_A + " = *(" + 类型名称 + "*)";
				m_Code += DEF_S(f_JIT_坐标取数组)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ");\n";
				break;
			}
		}
		m_Code += m_ReleaseCode;
		//m_Code += "}\n";
	}
	else {
		if (socket1->f_isLink()) {
			m_编译成功 = false;
		}
		outSocket1->f_setCode("");
		return "";
	}
	outSocket1->f_setCode(name_A);
	outSocket2->f_setCode(name_B);
	
	

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name_A));
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name_B));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name_A);
		释放 += f_代码构建_销毁数组(name_B);
	}
	return m_Code;
}

void C_取空间邻接数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_空间类型, 下一次读取数据指针);
		//下一次读取数据指针 = f_prop_Load(m_拷贝原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_取空间邻接数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_空间类型, 块);
	//f_prop_Save(m_填充, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建取空间邻接数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_取空间邻接数据节点(ctx);
}

C_节点基类* f_node_加载取空间邻接数据节点(S_设备环境& ctx, FILE* f) {
	C_取空间邻接数据节点* node = new C_取空间邻接数据节点(ctx);
	return node;
}

void f_node_保存取空间邻接数据节点(C_节点基类* n, FILE* f) {
	C_取空间邻接数据节点* node = dynamic_cast<C_取空间邻接数据节点*>(n);
}






C_数组打乱节点::C_数组打乱节点(S_设备环境& ctx) : C_节点基类(DEF_数组打乱节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"数组打乱");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建数组插座_I(u"数组");
	DEF_创建I32插座_I(u"种子");
	DEF_创建数组插座_O(u"数组");

	//m_排序方式 = f_alloc_EnumProp(nullptr, {
	//	{u"升序"},
	//	{u"降序"},
	//						  }, u"排序方式");
	//m_排序方式.m_私有 = true;
	//
	//m_排序算法 = f_alloc_EnumProp(nullptr, {
	//	{u"快速排序"},
	//	{u"基数排序"},
	//						  }, u"排序算法");
	//m_排序算法.m_私有 = true;

	m_拷贝原数据 = f_alloc_BoolProp(nullptr, u"拷贝");
	m_拷贝原数据.m_私有 = true;
	f_prop_Bool(m_拷贝原数据) = false;
}

C_数组打乱节点::~C_数组打乱节点() {
	//f_prop_Release(m_排序方式);
	//f_prop_Release(m_排序算法);
	f_prop_Release(m_拷贝原数据);
}

bool C_数组打乱节点::f_update() {
	return false;
}

std::string	C_数组打乱节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name;
	//bool 拷贝原数据 = f_prop_Bool(m_拷贝原数据);

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	auto* outSocket1 = f_get输出插座(1);

	f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_Array);
	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (socket1->f_isLink() && f_代码构建_是否为数组(接入的数据类型)) {
		
		socket1 = f_get输入插座(1);

		f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		outSocket1 = f_get输出插座(1);
		
		if (f_prop_Bool(m_拷贝原数据)) {
			name = f_getName();
			m_Code += f_node_getTypeName(接入的数据类型) + "* " + name + " = " + f_代码构建_创建数组(接入的数据类型, 0);
			m_Code += DEF_S(f_core_array_copy)"((S_Array*)" + name + ", (S_Array*)" + socket1->f_getCode(0) + ");\n";
		}
		else {
			name = socket1->f_getCode(0);
		}

		m_Code += "{\n";
		m_Code += socket1->f_构建变量代码(0);
		m_Code += socket2->f_构建变量代码(0);

		
		
		//auto 拷贝原数据 = f_代码构建_属性变量(m_拷贝原数据, f_getThis节点树());
		m_Code += DEF_S(f_JIT_打乱数组)"((S_Array*)" + name + ", " + socket2->f_getCode(0) + ");\n";

		m_Code += m_ReleaseCode;
		m_Code += "}\n";
	}
	else {
		outSocket1->f_setCode("");
		return "";
	}


	outSocket1->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (f_prop_Bool(m_拷贝原数据)) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (f_prop_Bool(m_拷贝原数据)) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_数组打乱节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_拷贝原数据, 下一次读取数据指针);
		//下一次读取数据指针 = f_prop_Load(m_拷贝原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_数组打乱节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_拷贝原数据, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建数组打乱节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_数组打乱节点(ctx);
}

C_节点基类* f_node_加载数组打乱节点(S_设备环境& ctx, FILE* f) {
	C_数组打乱节点* node = new C_数组打乱节点(ctx);
	return node;
}

void f_node_保存数组打乱节点(C_节点基类* n, FILE* f) {
	C_数组打乱节点* node = static_cast<C_数组打乱节点*>(n);
}






C_索引数组排序节点::C_索引数组排序节点(S_设备环境& ctx) : C_节点基类(DEF_索引数组排序节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"索引数组排序");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建I32_1D插座_I(u"索引");
	DEF_创建iVec2_1D插座_O(u"索引映射");

	m_排序方式 = f_alloc_EnumProp(nullptr, {
		{u"升序"},
		{u"降序"},
							}, u"排序方式");
	m_排序方式.m_私有 = true;

	m_排序算法 = f_alloc_EnumProp(nullptr, {
		{u"快速排序"},
		{u"基数排序"},
							  }, u"排序算法");
	m_排序算法.m_私有 = true;

	//m_拷贝原数据 = f_alloc_BoolProp(nullptr, u"拷贝");
	//m_拷贝原数据.m_私有 = true;
	//f_prop_Bool(m_拷贝原数据) = false;
}

C_索引数组排序节点::~C_索引数组排序节点() {
	f_prop_Release(m_排序方式);
	f_prop_Release(m_排序算法);
}

bool C_索引数组排序节点::f_update() {
	return false;
}

std::string	C_索引数组排序节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();
	//bool 拷贝原数据 = f_prop_Bool(m_拷贝原数据);

	auto* socket1 = f_get输入插座(1);


	m_Code += DEF_S(S_iVec2Array*)" " + name + ";\n";
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);

	auto 排序方式 = f_代码构建_属性变量(m_排序方式, f_getThis节点树());
	auto 排序算法 = f_代码构建_属性变量(m_排序算法, f_getThis节点树());

	m_Code += name + " = " + DEF_S(f_core_index_sort)"(" + socket1->f_getCode(0) + ", " + 排序方式 + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		return "";
	}
	释放 += f_代码构建_销毁数组(name);
	return m_Code;
}

void C_索引数组排序节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_排序方式, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_排序算法, 下一次读取数据指针);
		//下一次读取数据指针 = f_prop_Load(m_拷贝原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_索引数组排序节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_排序方式, 块);
	f_prop_Save(m_排序算法, 块);
	//f_prop_Save(m_拷贝原数据, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建索引数组排序节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_索引数组排序节点(ctx);
}

C_节点基类* f_node_加载索引数组排序节点(S_设备环境& ctx, FILE* f) {
	C_索引数组排序节点* node = new C_索引数组排序节点(ctx);
	return node;
}

void f_node_保存索引数组排序节点(C_节点基类* n, FILE* f) {
	C_索引数组排序节点* node = static_cast<C_索引数组排序节点*>(n);
}




C_数组重排节点::C_数组重排节点(S_设备环境& ctx) : C_节点基类(DEF_数组重排节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"数组重排");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建数组插座_I(u"数组");
	DEF_创建iVec2_1D插座_I(u"索引");

	DEF_创建数组插座_O(u"数组");

	m_改变原数据 = f_alloc_BoolProp(nullptr, u"改变原数据");
	m_改变原数据.m_私有 = true;
	f_prop_Bool(m_改变原数据) = false;


	//if (link_tree) {
	//	C_节点基类::f_绑定子集节点树(link_tree);
	//}
	//else {
	//	auto* 子树 = f_node_Create函数节点树(false, u"fun_");
	//	C_节点基类::f_绑定子集节点树(link_tree);
	//	
	//	auto 输入组节点 = new C_输入组节点(ctx, 2);
	//	子树->f_添加节点(输入组节点);
	//	auto 输出组节点 = new C_输出组节点(ctx, 1);
	//	子树->f_添加节点(输出组节点);
	//
	//	输入组节点->m_插座可编辑 = true;
	//	输出组节点->m_插座可编辑 = false;
	//
	//	输入组节点->m_坐标 = { -200, 0 };
	//	输出组节点->m_坐标 = { 200, 0 };
	//
	//
	//	输入组节点->f_add插座(new C_数组插座(u"数组"), E_插座方向::e_插座Type_输出);
	//	输入组节点->f_add插座(new C_插座I32_1D(u"索引"), E_插座方向::e_插座Type_输出);
	//
	//	输出组节点->f_add插座(new C_数组插座(u"数组"), E_插座方向::e_插座Type_输入);
	//}
	//
	//f_绑定this节点树(m_当前节点所在节点树);
}

C_数组重排节点::~C_数组重排节点() {
	f_prop_Release(m_改变原数据);
}

bool C_数组重排节点::f_update() {
	return false;
}

std::string	C_数组重排节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name;
	bool 创建数组 = f_prop_Bool(m_改变原数据);

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	auto 接入的数据类型 = socket1->f_get接入的数据类型();
	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, 接入的数据类型);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, 接入的数据类型);


		name = f_node_getTypeName(接入的数据类型) + "* " + f_getName();
	}
	else {
		m_编译成功 = false;
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Array);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Array);
		f_get输出插座(1)->f_setCode("");
		return "";
	}
	socket1 = f_get输入插座(1);

	
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	
	if (创建数组) {
		m_Code += " = (" + f_node_getTypeName(接入的数据类型) + "*)";
		m_Code += DEF_S(f_core_array_shuffle)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", true);\n";
	}
	else {
		//m_Code += name + " = " + f_代码构建_创建Array(接入的数据类型, "0");
		name = socket1->f_getCode(0);
		m_Code += DEF_S(f_core_array_shuffle)"((S_Array*)" + name + ", " + socket2->f_getCode(0) + ", false);\n";
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_数组重排节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_改变原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_数组重排节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_改变原数据, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建数组重排节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_数组重排节点(ctx);
}

C_节点基类* f_node_加载数组重排节点(S_设备环境& ctx, FILE* f) {
	C_数组重排节点* node = new C_数组重排节点(ctx);
	return node;

	//std::wstring 链接的节点树名称;
	//
	//S_文件块 文件块 = f_file_读取文件块(f);
	//if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点子集树) {
	//	const uint8* 下一次读取数据指针 = 文件块.m_data;
	//	下一次读取数据指针 = f_解宽字符串(链接的节点树名称, 下一次读取数据指针);
	//}
	//
	//if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
	//	f_node_加载节点树(ctx, f);
	//}
	//
	//C_数组重排节点* node = new C_数组重排节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称]);
	//return node;
}

void f_node_保存数组重排节点(C_节点基类* n, FILE* f) {
	C_数组重排节点* node = static_cast<C_数组重排节点*>(n);

	//auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点子集树, S_节点数据::g_文件版本号);
	//S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	//
	//auto* tree = node->f_get子集树();
	//f_包宽字符串(块, node->f_get子集树()->m_IDName);
	//
	//if (tree->m_未保存或加载) {
	//	tree->m_未保存或加载 = false;
	//
	//	std::vector<C_节点树*> trees = { tree };
	//	f_node_保存节点树(trees, f);
	//}
}






C_数组抽取节点::C_数组抽取节点(S_设备环境& ctx) : C_节点基类(DEF_数组抽取节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"数组抽取");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建数组插座_I(u"数组");
	//DEF_创建I8_1D插座_I(u"遮罩");
	DEF_创建F32插座_v1_I(u"比率");
	DEF_创建I32插座_I(u"随机种子");

	DEF_创建数组插座_O(u"数组");

	m_抽取方式 = f_alloc_EnumProp(nullptr, {
		{u"随机", u""},
		{u"遮罩", u""},
		{u"截取", u""},
		{u"索引", u""},
	},u"改变原数据");
	m_抽取方式.m_私有 = true;
	f_prop_enum(m_抽取方式) = 0;

	m_改变原数据 = f_alloc_BoolProp(nullptr, u"改变原数据");
	m_改变原数据.m_私有 = true;
	f_prop_Bool(m_改变原数据) = false;

}

C_数组抽取节点::~C_数组抽取节点() {
	f_prop_Release(m_抽取方式);
	f_prop_Release(m_改变原数据);
}

bool C_数组抽取节点::f_update() {
	
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	//auto* socket4 = f_get输入插座(4);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();
	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, 接入的数据类型);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Array);
		return true;
	}

	switch (f_prop_enum(m_抽取方式)) {
		case 0: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
			break;
		}
		case 1: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8_1D);
			break;
		}
		case 2: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_iVec2);
			break;
		}
	}

	return false;
}

std::string	C_数组抽取节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();
	bool 改变原数据 = f_prop_Bool(m_改变原数据);

	switch (f_prop_enum(m_抽取方式)) {
		case 0: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
			break;
		}
		case 1: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8_1D);
			break;
		}
		case 2: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_iVec2);
			break;
		}
		case 3: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32_1D);
			break;
		}
	}
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	//auto* socket4 = f_get输入插座(4);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();
	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, 接入的数据类型);
	}
	else {
		m_编译成功 = false;
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Array);
		f_get输出插座(1)->f_setCode("");
		return "";
	}
	socket1 = f_get输入插座(1);


	auto 类型 = f_node_getTypeName(接入的数据类型);
	m_Code += 类型 + "* " + name + ";\n";

	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);
	m_Code += socket3->f_构建变量代码(0);
	//m_Code += socket4->f_构建变量代码(0);

	switch (f_prop_enum(m_抽取方式)) {
		case 0: {
			m_Code += name + " = (" + 类型 + "*)" + DEF_S(f_core_array_extract)"((S_Array*)";
			m_Code += socket1->f_getCode(0) + ", ";
			m_Code += socket2->f_getCode(0) + ", ";
			m_Code += socket3->f_getCode(0) + ", ";
			if (改变原数据) {
				m_Code += "true);\n";
			}
			else {
				m_Code += "false);\n";
			}
			break;
		}
		case 1: {
			m_Code += name + " = (" + 类型 + "*)" + DEF_S(f_core_array_MaskExtract)"((S_Array*)";
			m_Code += socket1->f_getCode(0) + ", ";
			m_Code += socket2->f_getCode(0) + ", ";
			//m_Code += socket3->f_getCode(0) + ", ";
			if (改变原数据) {
				m_Code += "true);\n";
			}
			else {
				m_Code += "false);\n";
			}
			break;
		}
		case 2: {
			m_Code += name + " = (" + 类型 + "*)" + DEF_S(f_core_array_CutOut)"((S_Array*)";
			m_Code += socket1->f_getCode(0) + ", ";
			m_Code += socket2->f_getCode(0) + ");\n";
			break;
		}
		case 3: {
			m_Code += name + " = (" + 类型 + "*)" + DEF_S(f_core_array_IndexExtract)"((S_Array*)";
			m_Code += socket1->f_getCode(0) + ", ";
			m_Code += socket2->f_getCode(0) + ", ";
			if (改变原数据) {
				m_Code += "true);\n";
			}
			else {
				m_Code += "false);\n";
			}
			break;
		}
	}
	
	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		return "";
	}
	释放 += f_代码构建_销毁数组(name);
	return m_Code;
}

void C_数组抽取节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_改变原数据, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_抽取方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_数组抽取节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_改变原数据, 块);
	f_prop_Save(m_抽取方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建数组抽取节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_数组抽取节点(ctx);
}

C_节点基类* f_node_加载数组抽取节点(S_设备环境& ctx, FILE* f) {
	C_数组抽取节点* node = new C_数组抽取节点(ctx);
	return node;
}

void f_node_保存数组抽取节点(C_节点基类* n, FILE* f) {
	C_数组抽取节点* node = static_cast<C_数组抽取节点*>(n);
}







C_坐标取数据节点::C_坐标取数据节点(S_设备环境& ctx) : C_节点基类(DEF_取空间邻接数据节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"取空间邻接数据");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建iVec3_1D插座_I(u"数组");
	DEF_创建iVec3插座_I(u"坐标");
	DEF_创建iVec3插座_I(u"分辨率");

	DEF_创建iVec3_1D插座_O(u"邻接");

	m_空间类型 = f_alloc_EnumProp(nullptr, {
		{u"体素", u""},
		{u"离散", u""},
							  }, u"空间类型");
	m_空间类型.m_私有 = true;
	f_prop_enum(m_空间类型) = 1;

}

C_坐标取数据节点::~C_坐标取数据节点() {
	f_prop_Release(m_空间类型);
}

bool C_坐标取数据节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(3);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_iVec3_1D);
		socket1 = f_get输入插座(1);

		f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		socket2 = f_get输入插座(2);
		outSocket1 = f_get输出插座(3);

		(S_Array*)DEF_iVec3插座_1D数据(outSocket1);
		f_JIT_坐标取数组((S_Array*)DEF_iVec3插座_1D数据(socket1), DEF_iVec3插座数据(socket2), DEF_iVec3插座数据(socket3));
	}

	return false;
}

std::string	C_坐标取数据节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();


	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(3);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_iVec3_1D);
		socket1 = f_get输入插座(1);

		f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		socket2 = f_get输入插座(2);
		outSocket1 = f_get输出插座(3);



		auto 类型名称 = f_node_getTypeName(接入的数据类型);
		m_Code += 类型名称 + "& " + name + " = ";
		m_Code += "{\n";

		m_Code += socket1->f_构建变量代码(0);
		m_Code += socket2->f_构建变量代码(0);
		m_Code += socket3->f_构建变量代码(0);

		switch (f_prop_enum(m_空间类型)) {
			case 0: {
				m_Code += name + "*(" + 类型名称 + "*)";
				m_Code += DEF_S(f_JIT_坐标取数组)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ");\n";
				break;
			}
			case 1: {
				m_Code += name + "*(" + 类型名称 + "*)";
				m_Code += DEF_S(f_JIT_坐标取数组)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ");\n";
				break;
			}
		}
		m_Code += m_ReleaseCode;
		m_Code += "}\n";
	}
	else {
		if (outSocket1->f_isLink()) {
			m_编译成功 = false;
		}
		outSocket1->f_setCode("");
		return "";
	}

	outSocket1->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		return "";
	}
	释放 += f_代码构建_销毁数组(name);
	return m_Code;
}

void C_坐标取数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_空间类型, 下一次读取数据指针);
		//下一次读取数据指针 = f_prop_Load(m_拷贝原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_坐标取数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_空间类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建坐标取数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_坐标取数据节点(ctx);
}

C_节点基类* f_node_加载坐标取数据节点(S_设备环境& ctx, FILE* f) {
	C_坐标取数据节点* node = new C_坐标取数据节点(ctx);
	return node;
}

void f_node_保存坐标取数据节点(C_节点基类* n, FILE* f) {
	C_坐标取数据节点* node = dynamic_cast<C_坐标取数据节点*>(n);
}





C_数组切片节点::C_数组切片节点(S_设备环境& ctx) : C_节点基类(DEF_取空间邻接数据节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"取空间邻接数据");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建iVec3_1D插座_I(u"数组");
	DEF_创建iVec3插座_I(u"坐标");
	DEF_创建iVec3插座_I(u"分辨率");

	DEF_创建iVec3_1D插座_O(u"邻接");

	m_切片轴向 = f_alloc_EnumProp(nullptr, {
		{u"Xp", u""},
		{u"Yp", u""},
		{u"Zp", u""},
		{u"离散", u""},
							  }, u"空间类型");
	m_切片轴向.m_私有 = true;
	f_prop_enum(m_切片轴向) = 0;

}

C_数组切片节点::~C_数组切片节点() {
	f_prop_Release(m_切片轴向);
}

bool C_数组切片节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(3);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		//f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_iVec3_1D);
		//socket1 = f_get输入插座(1);
		//
		//f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
		//f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		//socket2 = f_get输入插座(2);
		//outSocket1 = f_get输出插座(3);
		//
		//(S_Array*)DEF_iVec3插座_1D数据(outSocket1);
		//f_JIT_坐标取数组((S_Array*)DEF_iVec3插座_1D数据(socket1), DEF_iVec3插座数据(socket2), DEF_iVec3插座数据(socket3));
	}

	return false;
}

std::string	C_数组切片节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();


	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(3);

	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_I32_1D);
		socket1 = f_get输入插座(1);

		switch (socket1->m_Type) {
			case E_值类型::e_Type_F32_1D:
			case E_值类型::e_Type_I8_1D:
			case E_值类型::e_Type_I32_1D:
			case E_值类型::e_Type_UI32_1D: {
				f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_I32);
				break;
			}
			case E_值类型::e_Type_iVec3_1D: {
				f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
				break;
			}
			default:
				break;
		}
		
		f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		socket2 = f_get输入插座(2);
		outSocket1 = f_get输出插座(3);



		auto 类型名称 = f_node_getTypeName(接入的数据类型);
		m_Code += 类型名称 + "& " + name + " = ";
		m_Code += "{\n";

		m_Code += socket1->f_构建变量代码(0);
		m_Code += socket2->f_构建变量代码(0);
		m_Code += socket3->f_构建变量代码(0);

		switch (f_prop_enum(m_切片轴向)) {
			case 0: {
				m_Code += name + "*(" + 类型名称 + "*)";
				m_Code += DEF_S(f_JIT_坐标取数组)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ");\n";
				break;
			}
			case 1: {
				m_Code += name + "*(" + 类型名称 + "*)";
				m_Code += DEF_S(f_JIT_坐标取数组)"((S_Array*)" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ");\n";
				break;
			}
		}
		m_Code += m_ReleaseCode;
		m_Code += "}\n";
	}
	else {
		if (outSocket1->f_isLink()) {
			m_编译成功 = false;
		}
		outSocket1->f_setCode("");
		return "";
	}

	outSocket1->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		return "";
	}
	释放 += f_代码构建_销毁数组(name);
	return m_Code;
}

void C_数组切片节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_切片轴向, 下一次读取数据指针);
		//下一次读取数据指针 = f_prop_Load(m_拷贝原数据, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_数组切片节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_切片轴向, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建数组切片节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_数组切片节点(ctx);
}

C_节点基类* f_node_加载数组切片节点(S_设备环境& ctx, FILE* f) {
	C_数组切片节点* node = new C_数组切片节点(ctx);
	return node;
}

void f_node_保存数组切片节点(C_节点基类* n, FILE* f) {
	C_数组切片节点* node = dynamic_cast<C_数组切片节点*>(n);
}




C_数据切换节点::C_数据切换节点(S_设备环境& ctx) : C_节点基类(DEF数据切换节点, E_节点类型::e_节点Type_变量) {
	f_setWName(u"切换");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建I8_1D插座_I(u"开关");
	DEF_创建数组插座_I(u"数组A");
	DEF_创建数组插座_I(u"数组B");

	DEF_创建数组插座_O(u"新数组");

}

C_数据切换节点::~C_数据切换节点() {
	
}

bool C_数据切换节点::f_update() {
	auto* socket1 = f_get输入插座(1);

	f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_Array);
	auto* socket2 = f_get输入插座(2);
	f_su_切换后端插座类型(this, e_插座Type_输入, 3, socket2->m_Type);
	auto* socket3 = f_get输入插座(3);

	f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket2->m_Type);
	auto* outSocket1 = f_get输出插座(1);


	auto 接入的数据类型 = socket1->f_get接入的数据类型();

	if (f_代码构建_是否为数组(接入的数据类型)) {
		//f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 1, E_值类型::e_Type_iVec3_1D);
		//socket1 = f_get输入插座(1);
		//
		//f_su_切换后端插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
		//f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket1->m_Type);
		//socket2 = f_get输入插座(2);
		//outSocket1 = f_get输出插座(3);
		//
		//(S_Array*)DEF_iVec3插座_1D数据(outSocket1);
		//f_JIT_坐标取数组((S_Array*)DEF_iVec3插座_1D数据(socket1), DEF_iVec3插座数据(socket2), DEF_iVec3插座数据(socket3));
	}

	return false;
}

std::string	C_数据切换节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();


	auto* socket1 = f_get输入插座(1);
	
	f_su_插座类型切换到连入的插座类型(this, e_插座Type_输入, 2, E_值类型::e_Type_Array);
	auto* socket2 = f_get输入插座(2);
	f_su_切换后端插座类型(this, e_插座Type_输入, 3, socket2->m_Type);
	auto* socket3 = f_get输入插座(3);

	f_su_切换后端插座类型(this, e_插座Type_输出, 1, socket2->m_Type);
	auto* outSocket1 = f_get输出插座(1);
	

	auto 接入的数据类型 = socket2->f_get接入的数据类型();
	auto 类型名称 = f_node_getTypeName(接入的数据类型);
	bool 是否为指针 = f_代码构建_是否为指针(接入的数据类型);
	if (是否为指针) {
		m_Code += 类型名称 + "* " + name + ";\n";
	}
	else {
		m_Code += 类型名称 + " " + name + ";\n";
	}

	
	m_Code += "{\n";

	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);
	m_Code += socket3->f_构建变量代码(0);

	if (是否为指针) {
		m_Code += name + " = " + f_代码构建_创建数组(接入的数据类型, 0);
		m_Code += DEF_S(f_core_array_Switch)"(" + socket1->f_getCode(0) 
										+ ", (S_Array*)" + socket2->f_getCode(0) 
										+ ", (S_Array*)" + socket3->f_getCode(0) 
										+ ", (S_Array*)" + name + ");\n";
	}
	else {
		
	}
	

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	outSocket1->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (是否为指针) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (是否为指针) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_数据切换节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		//下一次读取数据指针 = f_prop_Load(m_切片轴向, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_数据切换节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_切片轴向, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建数据切换节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_数据切换节点(ctx);
}

C_节点基类* f_node_加载数据切换节点(S_设备环境& ctx, FILE* f) {
	C_数据切换节点* node = new C_数据切换节点(ctx);
	return node;
}

void f_node_保存数据切换节点(C_节点基类* n, FILE* f) {
	C_数据切换节点* node = dynamic_cast<C_数据切换节点*>(n);
}

